﻿

#if SRP_URP
#if UNITY_EDITOR
#define DEBUG_INFO
#endif
using Devil;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Rendering;
using UnityEngine.Timeline;

namespace GameToolkit
{
    [TrackClipType(typeof(VolumeProfileClip))]
    [TrackBindingType(typeof(Volume))]
    [TrackColor(0.8f, 0.1f, 0.7f)]
    public class VolumeProfileTrack : PlayableTrack
    {

        public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
        {
            var playable = ScriptPlayable<VolumeProfileMixer>.Create(graph, inputCount);// base.CreateTrackMixer(graph, go, inputCount);
            foreach (var clip in GetClips())
            {
                var postprofile = clip.asset as VolumeProfileClip;
                if (postprofile == null || postprofile.profile == null)
                    continue;
                clip.displayName = postprofile.profile.name;
            }
#if DEBUG_INFO
            playable.GetBehaviour().name = name;
#endif
            return playable;
        }
    }

    public class VolumeProfileMixer : PlayableBehaviour
    {
        VolumeProfile mProfile;
        Volume mBindVolume;
        VolumeProfileBlend[] mOverrides = new VolumeProfileBlend[2];
        int mOverrideNum;
        bool mDynamicBind = true;
        float mBlendWeight;
#if DEBUG_INFO
        public string name;
#endif

        public VolumeProfile profile { get { return mProfile; } }


        public void BindVolume(Volume volume)
        {
            mDynamicBind = volume == null;
            if (volume != mBindVolume)
            {
                if (mBindVolume != null && mBindVolume.profile == mProfile)
                    mBindVolume.profile = null;
                mBindVolume = volume;
                if (mBindVolume != null && mProfile != null)
                    mBindVolume.profile = mProfile;
            }
        }

        public override void OnGraphStart(Playable playable)
        {
            mProfile = ScriptableObject.CreateInstance<VolumeProfile>();
            mProfile.hideFlags |= HideFlags.DontSave;
#if DEBUG_INFO
            mProfile.name = string.IsNullOrEmpty(name) ? "Timeline Mixer" : name;
#endif
        }

        public override void OnGraphStop(Playable playable)
        {
            if (mBindVolume != null && mBindVolume.profile == mProfile)
            {
                mBindVolume.profile = null;
            }
            if (mDynamicBind)
                mBindVolume = null;
            if (mProfile != null)
            {
                GlobalUtil.Destroy(mProfile);
                mProfile = null;
            }
        }

        public void OverrideSettings(VolumeProfileBlend profile)
        {
            if (mOverrideNum < mOverrides.Length && profile.profile != null)
            {
                mOverrides[mOverrideNum++] = profile;
                mBlendWeight += profile.weight;
#if DEBUG_INFO
                if(mProfile != null)
                    mProfile.name = mOverrideNum == 1 ? profile.profile.name : ParallelUtils.Concat(mProfile.name , "," , profile.profile.name);
#endif
            }
        }

        public override void PrepareFrame(Playable playable, FrameData info)
        {
            mOverrideNum = 0;
            mBlendWeight = 0;
        }

        public override void ProcessFrame(Playable playable, FrameData info, object playerData)
        {
            if (mProfile != null)
            {
                mProfile.ClearSettings();
                if (mOverrideNum > 1)
                {
                    var fix = mOverrides[0];
                    fix.weight = 1;
                    mOverrides[0] = fix;
                }
                for (int i = 0; i < mOverrideNum; i++)
                {
                    var set = mOverrides[i];
                    mProfile.OverrideSettings(set);
                }
                //if (ParentMixer != null && info.effectiveWeight > 0)
                //    ParentMixer.OverrideSettings(new PostProcessProfileBlend(mProfile, info.effectiveWeight));

                var vol = mDynamicBind ? (playerData as Volume) : mBindVolume;
                if (mBindVolume != null && mBindVolume != vol && mBindVolume.profile == mProfile)
                    mBindVolume.profile = null;
                mBindVolume = vol;
                if (mBindVolume != null)
                {
                    mBindVolume.profile = mProfile;
                    mBindVolume.weight = mBlendWeight;
                }
            }
        }

    }

}

#endif